import {Component, Input, OnInit} from '@angular/core';
import Feature from 'ol/Feature.js';
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import Polyline from 'ol/format/Polyline.js';
import Point from 'ol/geom/Point.js';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer.js';
import BingMaps from 'ol/source/BingMaps.js';
import VectorSource from 'ol/source/Vector.js';
import {Circle as CircleStyle, Fill, Icon, Stroke, Style} from 'ol/style.js';
import {UtilComponent} from '../../interface/util-component.interface';
import {fromLonLat} from 'ol/proj';

// 线路动画
// TODO 当前数据源为国外数据，需切换成国内数据的一条线路。找line数据，生成VectorSource
@Component({
    selector: 'kylin-maker-animation',
    templateUrl: './maker-animation.component.html',
    styleUrls: ['./maker-animation.component.less']
})
export class MakerAnimationComponent implements OnInit, UtilComponent {
    // ---------- 接口实现 begin -------------- //
    hasContent = true;
    map: Map;

    @Input() set data(val) {
        Object.assign(this, val);
    };

    // ---------- 接口实现 end ---------------- // {
// This long string is placed here due to jsFiddle limitations.
    // It is usually loaded with AJAX.
    polyline = [
        'hldhx@lnau`BCG_EaC??cFjAwDjF??uBlKMd@}@z@??aC^yk@z_@se@b[wFdE??wFfE}N',
        'fIoGxB_I\\gG}@eHoCyTmPqGaBaHOoD\\??yVrGotA|N??o[N_STiwAtEmHGeHcAkiA}^',
        'aMyBiHOkFNoI`CcVvM??gG^gF_@iJwC??eCcA]OoL}DwFyCaCgCcCwDcGwHsSoX??wI_E',
        'kUFmq@hBiOqBgTwS??iYse@gYq\\cp@ce@{vA}s@csJqaE}{@iRaqE{lBeRoIwd@_T{]_',
        'Ngn@{PmhEwaA{SeF_u@kQuyAw]wQeEgtAsZ}LiCarAkVwI}D??_}RcjEinPspDwSqCgs@',
        'sPua@_OkXaMeT_Nwk@ob@gV}TiYs[uTwXoNmT{Uyb@wNg]{Nqa@oDgNeJu_@_G}YsFw]k',
        'DuZyDmm@i_@uyIJe~@jCg|@nGiv@zUi_BfNqaAvIow@dEed@dCcf@r@qz@Egs@{Acu@mC',
        'um@yIey@gGig@cK_m@aSku@qRil@we@{mAeTej@}Tkz@cLgr@aHko@qOmcEaJw~C{w@ka',
        'i@qBchBq@kmBS{kDnBscBnFu_Dbc@_~QHeU`IuyDrC_}@bByp@fCyoA?qMbD}{AIkeAgB',
        'k_A_A{UsDke@gFej@qH{o@qGgb@qH{`@mMgm@uQus@kL{_@yOmd@ymBgwE}x@ouBwtA__',
        'DuhEgaKuWct@gp@cnBii@mlBa_@}|Asj@qrCg^eaC}L{dAaJ_aAiOyjByH{nAuYu`GsAw',
        'Xyn@ywMyOyqD{_@cfIcDe}@y@aeBJmwA`CkiAbFkhBlTgdDdPyiB`W}xDnSa}DbJyhCrX',
        'itAhT}x@bE}Z_@qW_Kwv@qKaaAiBgXvIm}A~JovAxCqW~WanB`XewBbK{_A`K}fBvAmi@',
        'xBycBeCauBoF}}@qJioAww@gjHaPopA_NurAyJku@uGmi@cDs[eRaiBkQstAsQkcByNma',
        'CsK_uBcJgbEw@gkB_@ypEqDoqSm@eZcDwjBoGw`BoMegBaU_`Ce_@_uBqb@ytBwkFqiT_',
        'fAqfEwe@mfCka@_eC_UmlB}MmaBeWkkDeHwqAoX}~DcBsZmLcxBqOwqE_DkyAuJmrJ\\o',
        '~CfIewG|YibQxBssB?es@qGciA}RorAoVajA_nAodD{[y`AgPqp@mKwr@ms@umEaW{dAm',
        'b@umAw|@ojBwzDaaJsmBwbEgdCsrFqhAihDquAi`Fux@}_Dui@_eB_u@guCuyAuiHukA_',
        'lKszAu|OmaA{wKm}@clHs_A_rEahCssKo\\sgBsSglAqk@yvDcS_wAyTwpBmPc|BwZknF',
        'oFscB_GsaDiZmyMyLgtHgQonHqT{hKaPg}Dqq@m~Hym@c`EuiBudIabB{hF{pWifx@snA',
        'w`GkFyVqf@y~BkoAi}Lel@wtc@}`@oaXi_C}pZsi@eqGsSuqJ|Lqeb@e]kgPcaAu}SkDw',
        'zGhn@gjYh\\qlNZovJieBqja@ed@siO{[ol\\kCmjMe\\isHorCmec@uLebB}EqiBaCg}',
        '@m@qwHrT_vFps@kkI`uAszIrpHuzYxx@e{Crw@kpDhN{wBtQarDy@knFgP_yCu\\wyCwy',
        'A{kHo~@omEoYmoDaEcPiuAosDagD}rO{{AsyEihCayFilLaiUqm@_bAumFo}DgqA_uByi',
        '@swC~AkzDlhA}xEvcBa}Cxk@ql@`rAo|@~bBq{@``Bye@djDww@z_C_cAtn@ye@nfC_eC',
        '|gGahH~s@w}@``Fi~FpnAooC|u@wlEaEedRlYkrPvKerBfYs}Arg@m}AtrCkzElw@gjBb',
        'h@woBhR{gCwGkgCc[wtCuOapAcFoh@uBy[yBgr@c@iq@o@wvEv@sp@`FajBfCaq@fIipA',
        'dy@ewJlUc`ExGuaBdEmbBpBssArAuqBBg}@s@g{AkB{bBif@_bYmC}r@kDgm@sPq_BuJ_',
        's@{X_{AsK_d@eM{d@wVgx@oWcu@??aDmOkNia@wFoSmDyMyCkPiBePwAob@XcQ|@oNdCo',
        'SfFwXhEmOnLi\\lbAulB`X_d@|k@au@bc@oc@bqC}{BhwDgcD`l@ed@??bL{G|a@eTje@',
        'oS~]cLr~Bgh@|b@}Jv}EieAlv@sPluD{z@nzA_]`|KchCtd@sPvb@wSb{@ko@f`RooQ~e',
        '[upZbuIolI|gFafFzu@iq@nMmJ|OeJn^{Qjh@yQhc@uJ~j@iGdd@kAp~BkBxO{@|QsAfY',
        'gEtYiGd]}Jpd@wRhVoNzNeK`j@ce@vgK}cJnSoSzQkVvUm^rSgc@`Uql@xIq\\vIgg@~k',
        'Dyq[nIir@jNoq@xNwc@fYik@tk@su@neB}uBhqEesFjoGeyHtCoD|D}Ed|@ctAbIuOzqB',
        '_}D~NgY`\\um@v[gm@v{Cw`G`w@o{AdjAwzBh{C}`Gpp@ypAxn@}mAfz@{bBbNia@??jI',
        'ab@`CuOlC}YnAcV`@_^m@aeB}@yk@YuTuBg^uCkZiGk\\yGeY}Lu_@oOsZiTe[uWi[sl@',
        'mo@soAauAsrBgzBqgAglAyd@ig@asAcyAklA}qAwHkGi{@s~@goAmsAyDeEirB_{B}IsJ',
        'uEeFymAssAkdAmhAyTcVkFeEoKiH}l@kp@wg@sj@ku@ey@uh@kj@}EsFmG}Jk^_r@_f@m',
        '~@ym@yjA??a@cFd@kBrCgDbAUnAcBhAyAdk@et@??kF}D??OL'
    ].join('');
    animating: any;
    speedInput: any;
    startButton: any;
    now: any;
    speed = 500;
    geoMarker: any;
    routeCoords: any;
    routeLength: any;
    center: any;
    styles: any;
    mapBackup: any;
    vectorLayer: any;
    textContent = '开启动画';

    constructor() {
    }

    ngOnInit() {
        this.turnOn();
    }

    turnOn() {
        const route = /** @type {module:ol/geom/LineString~LineString} */ (new Polyline({
            factor: 1e6
        }).readGeometry(this.polyline, {
            dataProjection: 'EPSG:4326',
            featureProjection: 'EPSG:3857'
        }));

        this.routeCoords = (route as any).getCoordinates();
        this.routeLength = this.routeCoords.length;

        const routeFeature = new Feature({
            type: 'route',
            geometry: route
        });
        const geoMarker = new Feature({
            type: 'geoMarker',
            geometry: new Point(this.routeCoords[0])
        });
        this.geoMarker = geoMarker;
        const startMarker = new Feature({
            type: 'icon',
            geometry: new Point(this.routeCoords[0])
        });
        const endMarker = new Feature({
            type: 'icon',
            geometry: new Point(this.routeCoords[this.routeLength - 1])
        });

        this.styles = {
            'route': new Style({
                stroke: new Stroke({
                    width: 6, color: [237, 212, 0, 0.8]
                })
            }),
            'icon': new Style({
                image: new Icon({
                    anchor: [0.5, 1],
                    src: './assets/img/castleMaker.png'
                })
            }),
            'geoMarker': new Style({
                image: new CircleStyle({
                    radius: 7,
                    fill: new Fill({color: 'black'}),
                    stroke: new Stroke({
                        color: 'white', width: 2
                    })
                })
            })
        };

        // const animating = false;
        /* const speedInput = document.getElementById('maker-animation-speed');
         this.speedInput = speedInput*/

        this.vectorLayer = new VectorLayer({
            source: new VectorSource({
                features: [routeFeature, geoMarker, startMarker, endMarker]
            }),
            style: (feature) => {
                // hide geoMarker if animation is active
                if (this.animating && feature.get('type') === 'geoMarker') {
                    return null;
                }
                return this.styles[feature.get('type')];
            }
        });

        this.center = fromLonLat([-49.8969, -29.8196]);
        /*const map = new Map({
            target: document.getElementById('maptest'),
            loadTilesWhileAnimating: true,
            view: new View({
                center: center,
                zoom: 10,
                minZoom: 2,
                maxZoom: 19
            }),
            layers: [
                new TileLayer({
                    source: new BingMaps({
                        imagerySet: 'AerialWithLabels',
                        key: 'AmQGw-4WGzWsh5iEn6QOJfk4UKe1gdTK9IGdrzh_kgU2jTT6e9U7XLOM7ck5r17_'
                    })
                }),
                vectorLayer
            ]
        });*/

        const view = this.map.getView();
        this.mapBackup = {
            zoom: view.getZoom(),
            center: view.getCenter()
        };
        view.setCenter(this.center);
        view.setZoom(9);
        this.map.addLayer(this.vectorLayer);
        // (this.map as any).loadTilesWhileAnimating_ = true;
    }


    moveFeature = (event) => {
        const vectorContext = event.vectorContext;
        const frameState = event.frameState;

        if (this.animating) {
            const elapsedTime = frameState.time - this.now;
            // here the trick to increase speed is to jump some indexes
            // on lineString coordinates
            const index = Math.round(this.speed * elapsedTime / 1000);

            if (index >= this.routeLength) {
                this.stopAnimation(true);
                return;
            }

            const currentPoint = new Point(this.routeCoords[index]);
            const feature = new Feature(currentPoint);
            vectorContext.drawFeature(feature, this.styles.geoMarker);
        }
        // tell OpenLayers to continue the postcompose animation
        this.map.render();
    }
    startAnimation = () => {
        if (this.animating) {
            this.stopAnimation(false);
        } else {
            this.animating = true;
            this.now = new Date().getTime();
            // this.speed = this.speedInput.value;
            this.textContent = '取消动画';
            // hide geoMarker
            this.geoMarker.setStyle(null);
            // just in case you pan somewhere else
            this.map.getView().setCenter(this.center);
            this.map.on('postcompose', this.moveFeature);
            this.map.render();
        }
    }

    /**
     * @param {boolean} ended end of animation.
     */
    stopAnimation = (ended) => {
        this.animating = false;
        this.textContent = '开启动画';

        // if animation cancelled set the marker at the beginning
        const coord = ended ? this.routeCoords[this.routeLength - 1] : this.routeCoords[0];
        /** @type {module:ol/geom/Point~Point} */ (this.geoMarker.getGeometry())
            .setCoordinates(coord);
        // remove listener
        this.map.un('postcompose', this.moveFeature);
    }

    cancel(options?: any): any {
        this.map.removeLayer(this.vectorLayer);
        this.map.getView().setZoom(this.mapBackup.zoom);
        this.map.getView().setCenter(this.mapBackup.center);
    }
}
